/**
 * 资源文件管理模块
 * @file resource.js
 * @author Verning Aulence
 * @date 2021-09-14 16:18:06
 */

const express = require('express');
const router = express.Router();
const path = require('path');
// 自定义数据库模块
const {Mongoose, ResourceSchema} = require('../modules/db');
// 资源文件的上传处理模块
const multer = require('multer');
// 生成资源的随机不重复名称
const {nanoid} = require('nanoid');
// 文件操作模块
const fs = require('fs');
// 图片压缩处理模块
const compressImage = require('images');

// 处理POST请求的中间件配置
router.use(express.json());
router.use(express.urlencoded({ extended: true }));

// multer的配置
const fileStorage = multer.diskStorage({
    // 文件目录
	destination(req, file, callback) {
        // 获取文件类型（复数形式）
        const fileType = file.mimetype.slice(0, file.mimetype.indexOf('/')) + 's';
        
        // 获取资源上传的用户名
        const uploadFromUser = req.headers.username;

        console.dir(`上传的文件类型是“${fileType}”，用户是“${uploadFromUser}”`);

        // 判断用户目录是否存在
        const hasUserDirPath = fs.existsSync(`assets/${fileType}/${uploadFromUser}`);
        // 如果用户目录不存在则创建一个用户目录
        if(!hasUserDirPath) {
            // 创建用户目录和预览目录
            fs.mkdirSync(`assets/${fileType}/${uploadFromUser}`);
            fs.mkdirSync(`assets/${fileType}/${uploadFromUser}/preview`);
        }

        // 设置路径回调
		callback(null, `assets/${fileType}/${uploadFromUser}`);
	},
    // 文件命名
	filename(req, file, callback) {
		callback(null, nanoid(32) + path.extname(file.originalname))
	}
});

// 资源首页
router.get('/', (req, res) => {
    res.status(404).send('找不到页面');
});

// 上传图片信息
router.post('/uploadp_picture', (req, res) => {
    // 获取资源上传的用户名
    const uploadFromUser = req.headers.username;

    // 文件类型
    let fileType = '';

    // 调用文件上传插件来定义上传规则
	const pictureUploader = multer({
		storage: fileStorage,
        fileFilter(req, file, callback) {
            // 获取上传文件的MIME
            const mimetype = file.mimetype;
            // 获取文件类型
            fileType = mimetype.slice(0, mimetype.indexOf('/'));
            // 验证通过
            callback(null, true);
        },
        limits: { fileSize: 1024 * 5000 }
	}).single('uploadfile');

    // 使用该规则进行文件上传
	pictureUploader(req, res, function(err) {
        if(err) {
            console.error('图片上传不符合要求：',err);
            return;
        };
        // 获取图片表单录入信息
        const resourceInfo = req.body;
        // 获取上传的图片信息
        const resource = req.file; 

        console.log(resourceInfo);

        // 为图片添加路径
        resourceInfo.fileSavePath = `assets/images/${uploadFromUser}/${resource.filename}`;

        // 添加上传用户的信息
        resourceInfo.uploadFromUser = uploadFromUser;

        // 获取文件名和后缀
        const fileName = resource.filename.slice(0, resource.filename.lastIndexOf('.'));
        const extName = resource.filename.slice(resource.filename.lastIndexOf('.'));

        // 获取图片文件子类型
        let childType = resource.mimetype;
        childType = childType.slice(childType.indexOf('/') + 1);
        
        // 获取图片实际宽度
        const orginWidth = resourceInfo.imageNaturalWidth;
        const orginHeight = resourceInfo.imageNaturalHeight;

        // 只对 jpeg（包括jpg）和 png 两种格式且宽高大于720像素的图片做压缩操作
        if((childType === 'jpeg' || childType === 'png') &&
            (orginWidth > 720 || orginHeight > 720)) {
            // 压缩处理图片
            compressImage(`./assets/images/${uploadFromUser}/${resource.filename}`)
                .resize(720)
                .save(`./assets/images/${uploadFromUser}/preview/${fileName}.preview${extName}`, {
                    quality : 65 
                });

            // 存储预览图的路径
            resourceInfo.filePreviewSavePath = `assets/images/${uploadFromUser}/preview/${fileName}.preview${extName}`;
        }

        // 创建图片的数据模型
        const ResourceModel = Mongoose.model(`${uploadFromUser}_resource`, ResourceSchema);

        // 需要存储的图片
        const newResource = new ResourceModel(resourceInfo);
        newResource.save((err, prod) => {
            if(err) {
                res.send({
                    result: 'error',
                    reason: err
                });
                return;
            }

            res.json({
                result: 'success',
                resourceInfo
            });
        });
        
	});
});

// 修改图片信息
router.post('/edit_picture', (req, res) => {
    // 获取资源上传的用户名
    const uploadFromUser = req.headers.username;

    // 文件类型
    let fileType = '';

    // 调用文件上传插件来定义上传规则
	const upload = multer({
		storage: fileStorage,
        fileFilter(req, file, callback) {
            // 获取上传文件的MIME
            const mimetype = file.mimetype;
            // 获取文件类型
            fileType = mimetype.slice(0, mimetype.indexOf('/'));
            console.log('上传的文件类型是：' + mimetype);
            // 验证通过
            callback(null, true);
        },
        limits: { fileSize: 1024 * 5000 }
	}).single('uploadfile');

    // 使用该规则进行文件上传
	upload(req, res, function(err) {
        if(err) {
            console.error('图片上传不符合要求：',err);
            return;
        };
        // 获取图片录入信息
        const resourceInfo = req.body;

        // 获取上传的图片信息
        const resource = req.file; 

        /**** 如果图片经过了更改 ****/
        if(resource) {
            // 为图片添加路径
            resourceInfo.fileSavePath = `assets/images/${uploadFromUser}/${resource.filename}`;

            // 获取文件名和后缀
            const fileName = resource.filename.slice(0, resource.filename.lastIndexOf('.'));
            const extName = resource.filename.slice(resource.filename.lastIndexOf('.'));

            // 获取图片文件子类型
            let childType = resource.mimetype;
            childType = childType.slice(childType.indexOf('/') + 1);

            // 获取图片实际宽度
            const orginWidth = resourceInfo.imageNaturalWidth;
            const orginHeight = resourceInfo.imageNaturalHeight;

            // 只对 jpeg（包括jpg）和 png 两种格式做压缩操作
            if((childType === 'jpeg' || childType === 'png') &&
                (orginWidth > 720 || orginHeight > 720)) {
                // 调用压缩图片模块进行处理
                compressImage(`./assets/images/${uploadFromUser}/${resource.filename}`)
                    .resize(720)
                    .save(`./assets/images/${uploadFromUser}/preview/${fileName}.preview${extName}`, {
                        quality : 65 
                    });

                // 存储预览图的路径
                resourceInfo.filePreviewSavePath = `assets/images/${uploadFromUser}/preview/${fileName}.preview${extName}`;
            }

            // 创建图片的数据模型
            const ResourceModel = Mongoose.model(`${uploadFromUser}_resource`, ResourceSchema);

            // 更新数据库信息
            ResourceModel.findByIdAndUpdate(resourceInfo.resourceID, {
                classify: resourceInfo.classify,
                fileName: resourceInfo.fileName,
                classify: resourceInfo.classify,
                description: resourceInfo.description,
                uploadDate: resourceInfo.uploadDate,
                fileName: resourceInfo.fileName,
                resoOriginName: resourceInfo.resoOriginName,
                fileSavePath: resourceInfo.fileSavePath,
                filePreviewSavePath: resourceInfo.filePreviewSavePath || '',
                resoType: resourceInfo.resoType,
                resoSize: resourceInfo.resoSize,
                imageNaturalWidth: resourceInfo.imageNaturalWidth,
                imageNaturalHeight: resourceInfo.imageNaturalHeight,
                lastModifiedDate: resourceInfo.lastModifiedDate
            }, (err, origin) => {
                if(err) console.error('上传出现错误：',err);

                // 获取原来的图片路径
                const originResoPath = origin.fileSavePath;
                const originResoPrePath = origin.filePreviewSavePath || '';

                // 删除对应的图片路径
                fs.unlink(originResoPath, (err) => {
                    if(err) return console.error(err);
                });
                // 删除对应的预览图片路径
                fs.unlink(originResoPrePath, (err) => {
                    if(err) return console.error(err);
                });

                // 向客户端返回更新结果
                res.json({ 
                    result: 'success',
                    // 返回图片原始信息
                    originInfo: origin
                });
            });
        }
        /**** 如果只更改了图片信息，而没有更新图片 ****/
        else {
            // 创建图片的数据模型
            const ResourceModel = Mongoose.model(`${uploadFromUser}_resource`, ResourceSchema);

            // 更新数据库信息
            ResourceModel.findByIdAndUpdate(resourceInfo.resourceID, {
                classify: resourceInfo.classify,
                fileName: resourceInfo.fileName,
                classify: resourceInfo.classify,
                description: resourceInfo.description,
                uploadDate: resourceInfo.uploadDate
            }, (err, origin) => {
                if(err) console.error('上传出现错误：',err);

                // 向客户端返回更新结果
                res.json({ 
                    result: 'success',
                    // 返回图片原始信息
                    originInfo: origin
                });
            });
        }
	});
});

// 单个资源删除
router.delete('/delete/:usename/:rid', async (req, res) => {
    // 获取资源的ID
    const {usename, rid} = req.params;

    // 创建资源的数据模型
    const ResourceModel = Mongoose.model(`${usename}_resource`, ResourceSchema);

    // 删除资源文件
    const deleResoFile = await new Promise((resolve, reject) => {
        ResourceModel.findById(rid, (err, data) => {
            // 获取资源的路径
            const filePath = data.fileSavePath;
            // 获取资源的预览路径（为参与压缩过的图片时）
            const filePrePath = data.filePreviewSavePath;
            
            // 删除结果数组
            const deleteResult = [];

            // 执行文件删除
            fs.unlinkSync(filePath, (err) => {
                if(err) return reject(err);
                // 添加成功结果
                deleteResult.push(true);
            });
            // 如果包含预览文件（预览图）
            if(filePrePath) {
                // 执行预览文件删除
                fs.unlinkSync(filePrePath, (err) => {
                    if(err) return reject(err);
                    // 添加成功结果
                    deleteResult.push(true);
                });
            }
            // 如果全部删除成功，则返回 true 的值，否则返回 false
            resolve(deleteResult.every(item => item));
        })
    });

    // 删除资源信息和对应的文件
    const deleResoData = await new Promise((resolve, reject) => {
        // 删除本件商品
        ResourceModel.findByIdAndDelete(rid, (err) => {
            if(err) return reject(err);
            // 成功字符串标识
            resolve(true);
        });
    });

    // 删除资源的最终结果
    const deleResoResult = deleResoFile && deleResoData;

    // 成功返回
    if(deleResoResult) {
        res.json({
            result: 'success'
        });
    }
    // 失败返回
    else {
        res.status(500).json({
            result: 'Fail',
            reason: '数据已经被删除，或者资源存储路径不存在，也可能是服务器出现错误'
        });
    }
})

// 获取全部资源
router.post('/get_all_resource', (req, res) => {
    // 资源的数据模型
    const ResourceModel = Mongoose.model(`${req.body.username}_resource`, ResourceSchema);
    ResourceModel.find((err, resoInfo) => {
        if(err) {
            console.error(err);
            res.status(500).send('服务器查询出现错误');
        }
        
        // 克隆数组
        const resResourceInfo = [...resoInfo];
        // 处理资源文件路径
        resResourceInfo.forEach((resoItem, index, originArr) => {
            originArr[index].fileSavePath = '//' + req.headers.host + '/' + resoItem.fileSavePath;
            // 预览图片的处理
            const hasPreview = !!originArr[index].filePreviewSavePath;
            hasPreview ? 
                originArr[index].filePreviewSavePath = '//' + req.headers.host + '/' +
                    resoItem.filePreviewSavePath :
                originArr[index].filePreviewSavePath = '';
        });
        // 返回资源数据
        res.json(resResourceInfo);
    })
    // 按最新上传时间排序返回数据
    .sort({uploadDate: -1});
});

// 获取图片资源
router.get('/get_all_picture', (req, res) => {
    // 资源的数据模型
    const ResourceModel = Mongoose.model(`${req.query.username}_resource`, ResourceSchema);

    // 查询资源为图片的数据
    ResourceModel.find({classify: {$elemMatch: {$eq: '图片'}}}, (err, resoInfo) => {
        if(err) {
            console.error(err);
            res.status(500).send('服务器查询出现错误');
        }

        // 克隆数组
        const resResourceInfo = [...resoInfo];
        // 处理资源文件路径
        resResourceInfo.forEach((resoItem, index, originArr) => {
            // 返回一个不带域名和端口号的资源路径（相对于服务器根路径的文件路径）
            originArr[index].serverRootFileSavePath = resoItem.fileSavePath;
            // 原图路径的处理
            originArr[index].fileSavePath = '//' + req.headers.host + '/' + resoItem.fileSavePath;
            // 预览图片的处理
            const hasPreview = !!originArr[index].filePreviewSavePath;
            hasPreview ? 
                originArr[index].filePreviewSavePath = '//' + req.headers.host + '/' +
                    resoItem.filePreviewSavePath :
                originArr[index].filePreviewSavePath = '';
        });
            
        // 返回资源数据
        res.json(resResourceInfo);
    })
    // 按最新上传时间排序返回数据
    .sort({uploadDate: -1});
});

module.exports = router;